`timescale 1ns / 1ps
`include "top.vh"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/07/05 18:24:59
// Design Name: 
// Module Name: alu
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


/*
    m-bit alu with zero flag
*/
module alu(opA, opB, sel, out, zf);
    parameter m = 32;
    parameter sel_zero = 3'b000, sel_add = 3'b001, sel_sub = 3'b010, 
              sel_and = 3'b011, sel_or = 3'b100, sel_xor = 3'b101, 
              sel_sltu = 3'b110, sel_slts = 3'b111;
    
    input [m-1:0] opA, opB;
    input [2:0] sel;
    output [m-1:0] out;
    output zf;
    
    reg [m-1:0] o;
    reg flag;
    
    always @(opA, opB, sel)
    begin
        case (sel)
            sel_zero: o = 0;
            sel_add: o = opA + opB;
            sel_sub: o = opA - opB;
            sel_and: o = opA & opB;
            sel_or: o = opA | opB;
            sel_xor: o = opA ^ opB;
            sel_sltu: o = (opA < opB);
            sel_slts: 
            begin
                flag = (~(opA[m-1] ^ opB[m-1]) & (opA < opB)) | (opA[m-1] & ~opB[m-1]);
                o = flag;
            end
        endcase
    end
    
    assign out = o;
    assign zf = (o == 0);
endmodule